﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SyncLib.Data;
using System.ServiceModel;
using System.IO;
using log4net;
using SyncLib;
using System.Data;
using System.Data.SqlClient;
using SyncLib.Interface;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data;

namespace SyncWCFServiceLibrary
{
    public class SyncConfigManager : ISyncConfigManager
    {
        protected Guid ClientId { get; set; }
        static ILog Log = LogManager.GetLogger(typeof(Log4NetImplement));
        #region ISyncConfigManager Members

        public byte[] GetAssembly(Guid scopeExId)
        {
            ScopeInfoEx scope = new ScopeInfoEx();
            bool flag = false;
            try
            {
                scope.ScopeExId = scopeExId;
                scope.ClientID = ClientId;
                scope.LoadByScopeAndClientId();
                string assPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, scope.ClientAssembly);
                if (File.Exists(assPath))
                    return File.ReadAllBytes(assPath);
                else
                {
                    Log.ErrorFormat("Client({0}) Call GetAssembly with ScopeId={1} but {2} not found in application folder", ClientId, scopeExId, assPath);
                    flag = true;
                    throw new Exception("File not found " + scope.ClientAssembly);
                }
            }
            catch (Exception e)
            {
                if (!flag)
                    Log.Fatal(String.Format("Client({0}) call GetAssembly with ScopeId={1} but exception:", ClientId, scopeExId), e);
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("GetAssembly:", e));
            }

        }

        public byte[] GetFileOfSCope(Guid scopeExId, string fileKey)
        {
            FileOfScope f = new FileOfScope();
            bool flag = false;
            try
            {
                f.Load(scopeExId, fileKey);
                if (f.FileId.Equals(Guid.Empty))
                    throw new Exception(string.Format("No data found ScopeId={0} FileKey={1}", scopeExId, fileKey));

                string assPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, f.Path);
                if (File.Exists(assPath))
                    return File.ReadAllBytes(assPath);
                else
                {
                    Log.ErrorFormat("Client({0}) Call GetFileOfSCope with ScopeId={1} and FileKey={3} but {2} not found in application folder", ClientId, scopeExId, assPath, fileKey);
                    flag = true;
                    throw new Exception("File not found " + f.Path);
                }
            }
            catch (Exception e)
            {
                if (!flag)
                {
                    Log.Fatal(string.Format("Client({0}) Call GetFileOfSCope with ScopeId={1} and FileKey={2} but exception", ClientId, scopeExId, fileKey), e);
                }
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("GetAssembly:", e));
            }
        }



        public SyncLib.Data.ScopeInfoEx[] GetScopeInfo(Guid clientId)
        {
            string sql = "SELECT T1.[ScopeExId] " +
 "       ,[ScopeName] " +
 "       ,[Schema] " +
 "       ,[ServerAssembly] " +
 "       ,[ServerClass] " +
 "       ,[ClientAssembly] " +
 "       ,[ClientClass] " +
 "       ,T1.[ScopeVersion] " +
 "       ,T1.[SchemaVersion] " +
 "       ,[Comment] " +
 "       ,[ScopeType] " +
 "       ,CASE  WHEN T2.[Direction] IS NULL OR T2.[Direction] ='Undefine' THEN T1.[Direction] ELSE T2.[Direction] END [Direction]  " +
 "       ,[Ordinal] " +
 "       ,T1.[AssemblyVersion] " +
 "       ,[TemplateName] " +
 "       ,ISNULL(T2.[ClientId],'{1}') [ClientId] " +
 "       ,ISNULL(T2.[BatchSize],0) [BatchSize] " +
 "       ,ISNULL(T2.[ScopeVersion],0) [ClientScopeVersion] " +
 "       ,ISNULL(T2.[AssemblyVersion],0) [ClientAssemblyVersion] " +
 "       ,ISNULL(T2.[SchemaVersion],0) [ClientSchemaVersion] " +
 "       ,ISNULL(T2.[UploadFirst],1) [UploadFirst] " +
 "       ,ISNULL(T2.[DownloadFirst],1) [DownloadFirst] " +
 "       ,ISNULL(T2.[Enable],0) [Enable] " +
 "       ,ISNULL(T2.SyncTimes,0) SyncTimes "+
 "       ,ISNULL(T2.ConfigTimes,0) ConfigTimes "+
 "        " +
 "   FROM [dbo].[ScopeInfoEx] T1 " +
 "   LEFT JOIN [dbo].[ClientConfig] T2 " +
 "   ON T2.ScopeExid=T1.ScopeExId AND T2.ClientId='{1}' ";

            sql=string.Format(sql, CommonVariable.SyncConfigSchema, clientId);
            Log.Debug(sql);
            try
            {
                using (SqlDataReader reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql))
                {
                    List<ScopeInfoEx> lstData = new List<ScopeInfoEx>();
                    while (reader.Read())
                    {
                        ScopeInfoEx item = new ScopeInfoEx();
                        item.Populate(reader);
                        item.LoadTableOfScope();
                        lstData.Add(item);
                    }
                    return lstData.ToArray();
                }
            }
            catch (Exception ex)
            {
                Log.Fatal("GetScopeInfo Exception:", ex);
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("GetCommonScope:", ex), "Nothing");

            }

        }

        public ScopeInfoEx GetScopeInfoByName(string scopeName, Guid clientId)
        {
            string sql = "SELECT T1.[ScopeExId] " +
 "       ,[ScopeName] " +
 "       ,[Schema] " +
 "       ,[ServerAssembly] " +
 "       ,[ServerClass] " +
 "       ,[ClientAssembly] " +
 "       ,[ClientClass] " +
 "       ,T1.[ScopeVersion] " +
 "       ,T1.[SchemaVersion] " +
 "       ,[Comment] " +
 "       ,[ScopeType] " +
 "       ,CASE  WHEN T2.[Direction] IS NULL OR T2.[Direction] ='Undefine' THEN T1.[Direction] ELSE T2.[Direction] END [Direction]   " +
 "       ,[Ordinal] " +
 "       ,T1.[AssemblyVersion] " +
 "       ,[TemplateName] " +
 "       ,ISNULL(T2.[ClientId],'{1}') [ClientId] " +
 "       ,ISNULL(T2.[BatchSize],0) [BatchSize] " +
 "       ,ISNULL(T2.[ScopeVersion],0) [ClientScopeVersion] " +
 "       ,ISNULL(T2.[AssemblyVersion],0) [ClientAssemblyVersion] " +
 "       ,ISNULL(T2.[SchemaVersion],0) [ClientSchemaVersion] " +
 "       ,ISNULL(T2.[UploadFirst],1) [UploadFirst] " +
 "       ,ISNULL(T2.[DownloadFirst],1) [DownloadFirst] " +
 "       ,ISNULL(T2.[Enable],0) [Enable] " +
 "       ,ISNULL(T2.SyncTimes,0) SyncTimes " +
 "       ,ISNULL(T2.ConfigTimes,0) ConfigTimes " +
 "        " +
 "   FROM [{0}].[ScopeInfoEx] T1 " +
 "   LEFT JOIN [{0}].[ClientConfig] T2 " +
 "   ON T2.ScopeExid=T1.ScopeExId AND T2.ClientId='{1}' WHERE ScopeName=N'{2}'";

            sql = string.Format(sql, CommonVariable.SyncConfigSchema, clientId, scopeName);
            Log.Debug(sql);
            try
            {
                using (SqlDataReader reader = SqlHelper.ExecuteReader(CommonVariable.SqlConnectionString, CommandType.Text, sql))
                {

                    if (reader.Read())
                    {
                        ScopeInfoEx item = new ScopeInfoEx();
                        item.Populate(reader);
                        item.LoadTableOfScope();
                        return item;
                    }
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("GetCommonScope:", ex), "Nothing");
            }
        }


        #endregion

        #region ISyncConfigManager Members


        public void CreateScopeDescription(Microsoft.Synchronization.Data.DbSyncScopeDescription scopeDescription, ScopeInfoEx scope)
        {
            try
            {
                KeeperSyncUtility.CreateScopeDescription(scopeDescription, scope);
            }
            catch (Exception ex)
            {
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("CreateScopeDescription:", ex));

            }
        }
        public void CreateTemplateDescription(Microsoft.Synchronization.Data.DbSyncScopeDescription scopeDescription, ScopeInfoEx scope)
        {
            try
            {
                // KeeperSyncUtility.CreateTemplateDescription(scopeDescription, scope);
            }
            catch (Exception ex)
            {
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("CreateScopeDescription:", ex));

            }
        }

        public Microsoft.Synchronization.Data.DbSyncScopeDescription GetScopeDescription(ScopeInfoEx scope)
        {
            try
            {
                return KeeperSyncUtility.GetScopeDescription(scope);

            }
            catch (Exception ex)
            {
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("CreateScopeDescription:", ex));

            }

        }


        public bool ExistsScope(ScopeInfoEx scope)
        {
            try
            {
                return KeeperSyncUtility.ExistsScope(scope);
            }
            catch (Exception ex)
            {
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("CreateScopeDescription:", ex));

            }
        }

        public bool ExistsTemplate(ScopeInfoEx scope)
        {
            try
            {
                return KeeperSyncUtility.ExistsScope(scope);
            }
            catch (Exception ex)
            {
                throw new FaultException<WebSyncFaultException>(new WebSyncFaultException("CreateScopeDescription:", ex));

            }
        }

        #endregion

        public DbSyncScopeDescription GetTemplateDescription(ScopeInfoEx scope)
        {
            return null;
        }
        public string CheckClientId(Guid clientId)
        {
            try
            {
                object temp = SqlHelper.ExecuteScalar(CommonVariable.SqlConnectionString, CommandType.Text,
                     "Select ClientName+Des ClientInfo from Client Where ClientId='" + clientId.ToString() + "'");
                if (temp != DBNull.Value)
                    return temp.ToString();
            }
            catch (Exception e)
            {
                Log.Fatal("Check clientID=" + clientId.ToString(), e);
            }
            return "";
        }
        public Byte[] GetApplicationResource(string path, string type)
        {
            return null;
        }
    }
}
